home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_asm / 68kdis / robj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-03  |  18.0 KB  |  859 lines

  1. /*
  2.  *    SCCS:    @(#)robj.c    1.2    11/2/84    14:19:59
  3.  *    Read object files.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  *
  25.  *    This particular module will obviously have to be munged beyond
  26.  *    recognition for another object format.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <a.out.h>
  31. #include <ldfcn.h>
  32. #include <string.h>
  33. #include "unc.h"
  34.  
  35. void    gette(), getde(), setde(), putte(), putde();
  36. long    gettw(), getdw();
  37. void    reallst(), lclash(), nomem(), unimpl();
  38. void    addit();
  39. char    *malloc();
  40. long    lseek();
  41.  
  42. int    par_entry, par_round, nmods, donedrel, donebrel;
  43. struct    commit    abstab, comtab, dreltab;
  44. long    trelpos, drelpos, brelpos;
  45.  
  46. int *symord;    /* convert symbol index to symbol ordinal */
  47.  
  48. ef_fids    mainfile;
  49.  
  50. symbol    lookup(), inventsymb(), getnsymb();
  51.  
  52. #define RWORD 1
  53. #define RLONG 2
  54. #define    DBSIZE    100
  55. #define    STINIT    20
  56.  
  57. /*
  58.  *    Read text segment.  Return 0 if not ok.
  59.  */
  60.  
  61. int    rtext(ldptr, outf)
  62.   LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  63.   ef_fid    outf;        /*  Output file descriptor  */
  64. {
  65.    t_entry        tstr;
  66.    struct    aouthdr    unixhdr;
  67.    struct  scnhdr  sect;
  68.    register  long    size;
  69.    register  int    i, l;
  70.    unsigned  short    inbuf[DBSIZE/2];
  71.    
  72.    /*
  73.     *    Initialise fields in structure.
  74.     */
  75.    
  76.    tstr.t_type = T_UNKNOWN;
  77.    tstr.t_vins = 1;        /*  For the moment  */
  78.    tstr.t_bdest = 0;
  79.    tstr.t_gbdest = 0;
  80.    tstr.t_lng = 1;
  81.    tstr.t_reloc = R_NONE;
  82.    tstr.t_rdisp = 0;
  83.    tstr.t_isrel = 0;
  84.    tstr.t_amap = 0;
  85.     tstr.t_dref = 0;
  86.     tstr.t_relsymb = NULL;
  87.     tstr.t_reldisp = 0;
  88.     tstr.t_lab = NULL;
  89.     tstr.t_lsymb = 0;
  90.     tstr.t_refhi = 0;
  91.     tstr.t_reflo = 0x7fffffff;
  92.     tstr.t_match = 0;
  93.     
  94.     /*
  95.      *    Read a.out header.
  96.      */
  97.  
  98.     if (ldohseek(ldptr) == FAILURE) {    /* no optional header */
  99.  
  100.         outf->ef_entry = 0;
  101.         ldshread(ldptr,1,§);        /* text header */
  102.         outf->ef_tbase = sect.s_vaddr;
  103.         outf->ef_tsize = sect.s_size;
  104.  
  105.         ldshread(ldptr,2,§);        /* data header */
  106.         outf->ef_dbase = sect.s_vaddr;
  107.         outf->ef_dsize = sect.s_size;
  108.  
  109.         ldshread(ldptr,3,§);        /* bss header */
  110.         outf->ef_bbase = sect.s_vaddr;
  111.         outf->ef_bsize = sect.s_size;
  112.         outf->ef_end = sect.s_vaddr + sect.s_size;
  113.     } else {
  114.         FREAD((char *)&unixhdr,sizeof(struct aouthdr),1,ldptr);
  115.     
  116.         if ( N_BADMAG(unixhdr) )
  117.         return    0;
  118.  
  119.         outf->ef_entry = unixhdr.entry;
  120.         outf->ef_tbase = unixhdr.text_start;
  121.         outf->ef_dbase = unixhdr.data_start;
  122.         outf->ef_bbase = outf->ef_dbase + unixhdr.dsize;
  123.         outf->ef_end = outf->ef_bbase + unixhdr.bsize;
  124.  
  125.         outf->ef_tsize = unixhdr.tsize;
  126.         outf->ef_dsize = unixhdr.dsize;
  127.         outf->ef_bsize = unixhdr.bsize;
  128.     }
  129.     
  130.     ldsseek(ldptr,1);    /* seek to text section */
  131.     
  132.     size = outf->ef_tsize;
  133.     
  134.     while  (size > 1)  {
  135.         l = size > DBSIZE? DBSIZE: size;
  136.         if  (FREAD((char *)inbuf,1,l,ldptr) != l)
  137.             return    0;
  138.         l /= 2;
  139.         for  (i = 0;  i < l;  i++)  {
  140.             tstr.t_contents = inbuf[i];
  141.             (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  142.         }
  143.         size -= l + l;
  144.     }
  145.     
  146.     /*
  147.      *    Extra one to cope with "etext".
  148.      */
  149.     
  150.     (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  151.     return    1;
  152. }
  153. /*
  154.  *    Same sort of thing for the data segment.
  155.  */
  156.  
  157. int    rdata(ldptr, outf)
  158. LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  159. ef_fid    outf;        /*  Output file descriptor  */
  160. {
  161.     d_entry        dstr;
  162.     register  long    size;
  163.     register  int    i, l;
  164.     unsigned  char    inbuf[DBSIZE];
  165.  
  166.     /*
  167.      *    Initialise fields in structure.
  168.      */
  169.     
  170.     dstr.d_type = D_BYTE;
  171.     dstr.d_reloc = R_NONE;
  172.     dstr.d_lng = 1;
  173.     dstr.d_relsymb = NULL;
  174.     dstr.d_reldisp = 0;
  175.     dstr.d_lab = NULL;
  176.     
  177.     ldsseek(ldptr,2);    /* seek to data section */
  178.     
  179.     size = outf->ef_dsize;
  180.     
  181.     while  (size > 0)  {
  182.         l = size > DBSIZE? DBSIZE: size;
  183.         if  (FREAD((char *)inbuf,1,l,ldptr) != l)
  184.             return    0;
  185.         for  (i = 0;  i < l;  i++)  {
  186.             dstr.d_contents = inbuf[i];
  187.             (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  188.         }
  189.         size -= l;
  190.     }
  191.     
  192.     /*
  193.      *    Repeat for BSS segment.
  194.      */
  195.  
  196.     dstr.d_contents = 0;
  197.     for  (size = outf->ef_bsize;  size > 0;  size--)
  198.         (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  199.     
  200.     /*
  201.      *    Extra one to cope with "end".
  202.      */
  203.     
  204.     (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  205.     return    1;
  206. }
  207.  
  208. /*
  209.  *    Process symbol table segment.
  210.  */
  211.  
  212. int    rsymb(ldptr, dproc, outf)
  213. LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  214. symbol    (*dproc)();
  215. register  ef_fid  outf;    /*  Output file descriptor  */
  216. {
  217. #define SYMLENGTH 256
  218.     register  symbol  csym;
  219.      struct    syment    isym;
  220.     register  int   nsyms,symindex;
  221.     unsigned long   stroff;
  222.      char    inbuf[SYMLENGTH+1], *cp;
  223.     int ord;
  224.  
  225.     nsyms = HEADER(ldptr).f_nsyms;
  226.     stroff = HEADER(ldptr).f_symptr + nsyms*sizeof(struct syment);
  227.  
  228.     if  (nsyms <= 0)
  229.         nsyms = STINIT;
  230.  
  231.     outf->ef_stvec = (symbol *) malloc(nsyms * sizeof(symbol));
  232.     symord = (int *) malloc(nsyms * sizeof(int));
  233.     if  (outf->ef_stvec == NULL)
  234.         nomem();
  235.  
  236.     outf->ef_stcnt = 0;
  237.     outf->ef_stmax = nsyms;
  238.     ord = 0;
  239.     
  240.      for  (symindex=0; symindex<nsyms; symindex++)  {
  241.         ldtbread(ldptr,symindex,&isym);
  242.         if (isym.n_zeroes == 0) {    /* get from string table */
  243.             FSEEK(ldptr,stroff + isym.n_offset,0);
  244.             cp = inbuf;
  245.             do {
  246.              if (FREAD(cp,1,1,ldptr) != 1)/* Read symbol chars 1-by-1 */
  247.                  return 0;
  248.              if ( cp - inbuf >= SYMLENGTH )/* Check against buffer overflow */
  249.                  return 0;
  250.             } while (*cp++ != '\0');/* Terminate on null byte */
  251.         } else {            /* get from symbol field */
  252.             strncpy(inbuf,isym.n_name,8);
  253.             inbuf[8] = '\0';
  254.         }
  255.          csym = (*dproc)(lookup(inbuf), convtosun(&isym),
  256.                 isym.n_value, outf);
  257.          if (outf->ef_stcnt >= outf->ef_stmax)
  258.             reallst(outf);
  259.         outf->ef_stvec[outf->ef_stcnt++] = csym;
  260.         symord[symindex] = ord++;        /* record ordinal */
  261.         symindex += isym.n_numaux;        /* skip aux entries */
  262.     }
  263.     return    1;
  264. }
  265.  
  266. /*
  267.  *    Process relocation stuff.  -1 error, 0 no relocation, 1 relocation.
  268.  */
  269.  
  270. int    rrel(ldptr, ldptr2, outf)
  271. LDFILE *ldptr,*ldptr2;    /*  a.out file (possibly in library)  */
  272. ef_fid    outf;        /*  Output file descriptor  */
  273. {
  274.      struct    reloc    crel;
  275.     struct scnhdr tsect,dsect;
  276.     struct syment isym;
  277.     t_entry    tstr;
  278.     d_entry    dstr;
  279.     register  int    nreloc;
  280.     long    cont, pos;
  281.  
  282.     ldshread(ldptr,1,&tsect);
  283.     ldshread(ldptr,2,&dsect);
  284.      if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
  285.         return    0;
  286.  
  287.     nreloc = tsect.s_nreloc;
  288.  
  289.     ldrseek(ldptr,1);
  290.      while  (nreloc-- > 0)  {
  291.         if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  292.             return    -1;
  293.  
  294.          pos = crel.r_vaddr;
  295.         gette(outf, pos, &tstr);
  296.         if (crel.r_type == R_ABS)
  297.             tstr.t_reloc = R_NONE;
  298.         else
  299.             tstr.t_reloc = R_LONG;    /* what about PC-relative? */
  300.         ldtbread(ldptr2,crel.r_symndx,&isym);
  301.         if (isym.n_sclass == C_EXT) {
  302.              tstr.t_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
  303.              tstr.t_reldisp = gettw(outf, pos, (int)tstr.t_reloc);
  304.         }
  305.         else  {
  306.              cont = gettw(outf, pos, (int)tstr.t_reloc);
  307.              tstr.t_relsymb = getnsymb(outf, convtosun(&isym), cont);
  308.         }
  309.         tstr.t_relsymb->s_used++;
  310.         putte(outf, pos, &tstr);
  311.     }
  312.     
  313.     /*
  314.      *    And now repeat all that for data relocations.
  315.      */
  316.     
  317.     nreloc = dsect.s_nreloc;
  318.     
  319.     ldrseek(ldptr,2);
  320.      while  (nreloc-- > 0)  {
  321.         if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  322.             return    -1;
  323.  
  324.          pos = crel.r_vaddr;
  325.         getde(outf, pos, &dstr);
  326.         if (crel.r_type == R_ABS)
  327.             dstr.d_reloc = R_NONE;
  328.         else
  329.             dstr.d_reloc = R_LONG;    /* what about PC-relative? */
  330.  
  331.         ldtbread(ldptr2,crel.r_symndx,&isym);
  332.         if (isym.n_sclass == C_EXT) {
  333.              dstr.d_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
  334.              dstr.d_reldisp = getdw(outf, pos, (int)dstr.d_reloc);
  335.         }
  336.         else  {
  337.              cont = getdw(outf, pos, (int)dstr.d_reloc);
  338.              dstr.d_relsymb = getnsymb(outf, convtosun(&isym), cont);
  339.              if  (dstr.d_relsymb->s_type == S_TEXT)  {
  340.                 gette(outf, cont, &tstr);
  341.                 tstr.t_dref = 1;
  342.                 putte(outf, cont, &tstr);
  343.             }
  344.         }
  345.          switch  (dstr.d_reloc)  {
  346.         default:
  347.             unimpl("Data byte relocation");
  348.             break;
  349.         case  R_WORD:
  350.             unimpl("data word reloc");
  351.             dstr.d_type = D_WORD;
  352.             dstr.d_lng = 2;
  353.             setde(outf, pos+1, D_CONT, 1);
  354.             break;
  355.         case  R_LONG:
  356.             dstr.d_type = D_ADDR;
  357.             dstr.d_lng = 4;
  358.             setde(outf, pos+1, D_CONT, 1);
  359.             setde(outf, pos+2, D_CONT, 1);
  360.             setde(outf, pos+3, D_CONT, 1);
  361.             break;
  362.         }
  363.         dstr.d_relsymb->s_used++;
  364.         putde(outf, pos, &dstr);
  365.     }
  366.     return 1;
  367. }
  368.  
  369. /*
  370.  *    Process a symbol.
  371.  */
  372.  
  373. symbol    dosymb(sy, type, val, fid)
  374. register  symbol  sy;
  375. int    type;
  376. long    val;
  377. ef_fid    fid;
  378. {
  379.     t_entry    tstr;
  380.     d_entry    dstr;
  381.     
  382.     if  (!sy->s_newsym)  {
  383.          if  (type & S_EXT)  {
  384.             (void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name);
  385.             /* exit(10);  temporary? */
  386.         }
  387.         if  (++sy->s_defs > nmods)
  388.             nmods = sy->s_defs;
  389.         sy = inventsymb("DUP");
  390.     }
  391.  
  392.     sy->s_value = val;
  393.     
  394.     switch  (type)  {
  395.     default:
  396.         return    NULL;
  397.         
  398.      case  S_EXT|S_UNDF:
  399.         if  (val != 0)  {
  400.              sy->s_type = S_COMM;
  401.             addit(&comtab, sy);
  402.         }
  403.         else
  404.             sy->s_type = S_UNDF;
  405.         sy->s_glob = 1;
  406.         break;
  407.         
  408.      case  S_EXT|S_ABS:
  409.         sy->s_type = S_ABS;
  410.         sy->s_glob = 1;
  411.         addit(&abstab, sy);
  412.         break;
  413.         
  414.      case  S_ABS:
  415.         sy->s_type = S_ABS;
  416.         addit(&abstab, sy);
  417.         break;
  418.         
  419.      case  S_EXT|S_TEXT:
  420.      case  S_TEXT:
  421.         sy->s_type = S_TEXT;
  422.         gette(fid, val, &tstr);
  423.         tstr.t_bdest = 1;
  424.          if  (type & S_EXT)  {
  425.             tstr.t_gbdest = 1;
  426.             sy->s_glob = 1;
  427.         }
  428.         sy->s_link = tstr.t_lab;
  429.         tstr.t_lab = sy;
  430.         putte(fid, val, &tstr);
  431.         break;
  432.         
  433.      case  S_BSS:
  434.      case  S_EXT|S_BSS:
  435.         sy->s_type = S_BSS;
  436.         goto    datrest;
  437.      case  S_DATA:
  438.      case  S_EXT|S_DATA:
  439.         sy->s_type = S_DATA;
  440.     datrest:
  441.         getde(fid, val, &dstr);
  442.          if  (type & S_EXT)
  443.             sy->s_glob = 1;
  444.         sy->s_link = dstr.d_lab;
  445.         dstr.d_lab = sy;
  446.         putde(fid, val, &dstr);
  447.         break;
  448.     }
  449.     
  450.     sy->s_newsym = 0;
  451.     return    sy;
  452. }
  453.  
  454.  
  455. /*
  456.  *    Process relocation stuff in putative library modules.
  457.  *    The main function of all this is to mark which bits of the text
  458.  *    not to look at as I compare the stuff.
  459.  *
  460.  *    As with "rrel", return -1 error, 0 no relocation, 1 relocation.
  461.  */
  462.  
  463. int    rrell1(ldptr, outf)
  464. LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  465. ef_fid    outf;        /*  Output file descriptor  */
  466. {
  467.      struct    reloc    crel;
  468.     struct scnhdr tsect,dsect;
  469.     t_entry    tstr;
  470.     register  int    nreloc;
  471.     long    pos;
  472.  
  473.     ldshread(ldptr,1,&tsect);
  474.     ldshread(ldptr,2,&dsect);
  475.      if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
  476.         return    0;
  477.  
  478.     nreloc = tsect.s_nreloc;
  479.  
  480.     ldrseek(ldptr,1);
  481.      while  (nreloc-- > 0)  {
  482.         if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  483.             return    -1;
  484.  
  485.          pos = crel.r_vaddr;
  486.         gette(outf, pos, &tstr);
  487.         if (crel.r_type == R_ABS)
  488.             tstr.t_reloc = R_NONE;
  489.         else
  490.             tstr.t_reloc = R_LONG;    /* what about PC-relative? */
  491.         tstr.t_isrel = 1;
  492.         putte(outf, pos, &tstr);
  493.          if  (tstr.t_reloc == R_LONG)  {
  494.             gette(outf, pos+2, &tstr);
  495.             tstr.t_isrel = 1;
  496.             putte(outf, pos+2, &tstr);
  497.         }
  498.     }
  499.     
  500.     /*
  501.      *    Dont bother with data relocation at this stage. We'll
  502.      *    tie that up later.
  503.      */
  504.     
  505.     return 1;
  506. }
  507.  
  508. /*
  509.  *    Process a symbol in library file.  The extern variable trelpos gives
  510.  *    the place in the main file where the library module is relocated.
  511.  *    We don't know the data position until we do the final merge, perhaps
  512.  *    not even then.
  513.  */
  514. /* trelpos ??? */
  515.  
  516. symbol    dolsymb(sy, type, val, fid)
  517. register  symbol  sy;
  518. int    type;
  519. long    val;
  520. ef_fid    fid;
  521. {
  522.     t_entry    tstr;
  523.     
  524.     switch  (type)  {
  525.     default:
  526.         return    NULL;
  527.         
  528.      case  S_EXT|S_UNDF:
  529.         if  (!sy->s_newsym)
  530.             return    sy;
  531.         sy->s_value = val;
  532.         if  (val != 0)  {
  533.              sy->s_type = S_COMM;
  534.             addit(&dreltab, sy);
  535.         }
  536.         else
  537.             sy->s_type = S_UNDF;
  538.         sy->s_glob = 1;
  539.         break;
  540.         
  541.      case  S_EXT|S_ABS:
  542.         if  (!sy->s_newsym)  {
  543.             if  (sy->s_type != S_ABS || sy->s_value != val)
  544.                 lclash("abs");
  545.         }
  546.         sy->s_type = S_ABS;
  547.         sy->s_value = val;
  548.         sy->s_glob = 1;
  549.         addit(&abstab, sy);
  550.         break;
  551.         
  552.      case  S_EXT|S_TEXT:
  553.         sy->s_type = S_TEXT;
  554.         val += trelpos - fid->ef_tbase;
  555.         if  (!sy->s_newsym)  {
  556.             if  (val != sy->s_value)
  557.                 lclash("tsym");
  558.             return    sy;
  559.         }
  560.         sy->s_value = val;
  561.         gette(&mainfile, val, &tstr);
  562.         tstr.t_bdest = 1;
  563.         tstr.t_gbdest = 1;
  564.         sy->s_glob = 1;
  565.         sy->s_link = tstr.t_lab;
  566.         tstr.t_lab = sy;
  567.         putte(&mainfile, val, &tstr);
  568.         break;
  569.  
  570.      case  S_EXT|S_BSS:
  571.         if  (!sy->s_newsym)
  572.             return    sy;
  573.         sy->s_type = S_BSS;
  574.         sy->s_value = val - fid->ef_bbase;
  575.         goto    datrest;
  576.  
  577.      case  S_EXT|S_DATA:
  578.         if  (!sy->s_newsym)
  579.             return    sy;
  580.         sy->s_type = S_DATA;
  581.         sy->s_value = val - fid->ef_dbase;
  582.     datrest:
  583.         sy->s_glob = 1;
  584.         addit(&dreltab, sy);
  585.         break;
  586.     }
  587.     
  588.     sy->s_newsym = 0;
  589.     return    sy;
  590. }
  591.  
  592. /*
  593.  *    Change definition of undefined symbol as we define it.
  594.  */
  595.  
  596. void    reassign(sy, val)
  597. register  symbol  sy;
  598. long    val;
  599. {
  600.     sy->s_value = val;
  601.  
  602.     if  (val < mainfile.ef_tbase)  {
  603.         sy->s_type = S_ABS;
  604.         addit(&abstab, sy);
  605.     }
  606.     else  if  (val < mainfile.ef_dbase)  {
  607.         t_entry    tstr;
  608.         
  609.         sy->s_type = S_TEXT;
  610.         gette(&mainfile, val, &tstr);
  611.         tstr.t_bdest = 1;
  612.         tstr.t_gbdest = 1;
  613.         sy->s_glob = 1;
  614.         sy->s_link = tstr.t_lab;
  615.         tstr.t_lab = sy;
  616.         putte(&mainfile, val, &tstr);
  617.     }
  618.     else  {
  619.         d_entry dstr;
  620.         
  621.         sy->s_type = val < mainfile.ef_bbase? S_DATA: S_BSS;
  622.         getde(&mainfile, val, &dstr);
  623.         sy->s_link = dstr.d_lab;
  624.         dstr.d_lab = sy;
  625.         putde(&mainfile, val, &dstr);
  626.     }
  627. }
  628.  
  629. /*
  630.  *    When we discover where bss or data come, reallocate the table.
  631.  */
  632.  
  633. void    zapdat(seg, inc)
  634. int    seg;
  635. long    inc;
  636. {
  637.     register  int    i;
  638.     register  symbol  csymb;
  639.     d_entry    dent;
  640.     
  641.     for  (i = 0;  i < dreltab.c_int;  i++) {
  642.         csymb = dreltab.c_symb[i];
  643.         if  (csymb->s_type != seg)
  644.             continue;
  645.         csymb->s_value += inc;
  646.         getde(&mainfile, csymb->s_value, &dent);
  647.         csymb->s_link = dent.d_lab;
  648.         dent.d_lab = csymb;
  649.         putde(&mainfile, csymb->s_value, &dent);
  650.     }
  651. }
  652.  
  653. /*
  654.  *    Process relocation stuff in library module which we are inserting.
  655.  *    Horrors if something goes wrong.
  656.  */
  657. /* trelpos, drelpos ??? */
  658.  
  659. rrell2(ldptr, ldptr2, outf)
  660. LDFILE *ldptr,*ldptr2;    /*  a.out file (possibly in library)  */
  661. ef_fid    outf;        /*  Output file descriptor  */
  662. {
  663.      struct    reloc    crel;
  664.     t_entry    mtstr;
  665.     d_entry    mdstr;
  666.     struct scnhdr tsect,dsect;
  667.     struct syment isym;
  668.     int nreloc;
  669.     unsigned rtype;
  670.     register  long    size;
  671.     register  symbol  csymb;
  672.     long    pos, mpos, mval, lval;
  673.     int    dhere = 0;        /*  Mark whether bss done  */
  674.  
  675.     ldshread(ldptr,1,&tsect);
  676.     ldshread(ldptr,2,&dsect);
  677.      if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
  678.         return    0;
  679.  
  680.     nreloc = tsect.s_nreloc;
  681.  
  682.     ldrseek(ldptr,1);
  683.      while  (nreloc-- > 0)  {
  684.         if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  685.             lclash("rd trel");
  686.  
  687.          pos = crel.r_vaddr;
  688.          mpos = crel.r_vaddr + trelpos;
  689.         gette(&mainfile, mpos, &mtstr);
  690.         if (crel.r_type == R_ABS)
  691.             rtype = R_NONE;
  692.         else
  693.             rtype = R_LONG;    /* what about PC-relative? */
  694.         ldtbread(ldptr2,crel.r_symndx,&isym);
  695.          lval = gettw(outf, pos, (int)rtype);
  696.          mval = gettw(&mainfile, mpos, (int)rtype);
  697.         
  698.         if ( isym.n_sclass != C_EXT ) {
  699.         switch (convtosun(&isym)) {
  700.          case  S_TEXT:
  701.             if  (lval + trelpos - outf->ef_tbase != mval)
  702.                 lclash("Trel");
  703.             continue;
  704.          case  S_DATA:
  705.             if  (donedrel)  {
  706.                 if  (lval + drelpos - outf->ef_dbase != mval)
  707.                     lclash("Drel");
  708.             }
  709.             else  {
  710.                 donedrel++;
  711.                 drelpos = mval - lval + outf->ef_dbase;
  712.             }
  713.             continue;
  714.          case  S_BSS:
  715.             if  (donebrel)  {
  716.                 if  (lval + brelpos - outf->ef_bbase != mval)
  717.                     lclash("brel");
  718.             }
  719.             else  {
  720.                 donebrel++;
  721.                 brelpos = mval - lval + outf->ef_bbase;
  722.             }
  723.             continue;
  724.                }
  725.            } else {
  726.              if  (crel.r_symndx >= outf->ef_stcnt)
  727.                 lclash("Bad sy no");
  728.              csymb = outf->ef_stvec[symord[crel.r_symndx]];
  729.             if  (csymb == NULL)
  730.                 continue;
  731.             switch  (csymb->s_type)  {
  732.             case  S_UNDF:
  733.                 reassign(csymb, mval - lval);
  734.                 break;
  735.             case  S_ABS:
  736.                 if  (lval + csymb->s_value != mval)
  737.                     lclash("abs rel");
  738.                 break;
  739.             case  S_TEXT:
  740.                 if  (lval + csymb->s_value != mval)
  741.                     lclash("text rel");
  742.                 break;
  743.             case  S_DATA:
  744.                 if  (lval + csymb->s_value != mval)
  745.                     lclash("data rel");
  746.                 break;
  747.             case  S_BSS:
  748.                 if  (lval + csymb->s_value != mval)
  749.                     lclash("bss rel");
  750.                 break;
  751.              case  S_COMM:
  752.                 reassign(csymb, mval - lval);
  753.                 break;
  754.             }
  755.             mtstr.t_relsymb = csymb;
  756.             mtstr.t_reldisp = lval;
  757.         }
  758.     }
  759.     
  760.     /*
  761.      *    Relocate data and bss if possible.
  762.      */
  763.     
  764.     if  (donebrel)  {
  765.         zapdat(S_BSS, brelpos);
  766.         dhere++;
  767.     }
  768.     
  769.     if  (!donedrel)
  770.         return;
  771.         
  772.  
  773.     zapdat(S_DATA, drelpos);
  774.     
  775.     /*
  776.      *    And now repeat all that for data relocations if possible
  777.      */
  778.     
  779.     nreloc = tsect.s_nreloc;
  780.  
  781.     ldrseek(ldptr,2);
  782.     
  783.     while (nreloc-- > 0) {
  784.         if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  785.             lclash("Rd drel");
  786.  
  787.          if  (crel.r_type == R_ABS)
  788.             continue;
  789.  
  790.          pos = crel.r_vaddr;
  791.          mpos = crel.r_vaddr + drelpos;
  792.         getde(&mainfile, mpos, &mdstr);
  793.         rtype = R_LONG;        /* what about PC-relative? */
  794.         ldtbread(ldptr2,crel.r_symndx,&isym);
  795.  
  796.          lval = getdw(outf, pos, (int)rtype);
  797.          mval = getdw(&mainfile, mpos, (int)rtype);
  798.         if ( isym.n_sclass != C_EXT ) {
  799.         switch (convtosun(&isym)) {
  800.          case  S_TEXT:
  801.             if  (lval + trelpos - outf->ef_tbase != mval)
  802.                 lclash("Trel-d");
  803.             continue;
  804.          case  S_DATA:
  805.             if  (lval + drelpos - outf->ef_dbase != mval)
  806.                 lclash("Drel-d");
  807.             continue;
  808.          case  S_BSS:
  809.             if  (donebrel)  {
  810.                 if  (lval + brelpos - outf->ef_bbase != mval)
  811.                     lclash("brel");
  812.             }
  813.             else  {
  814.                 donebrel++;
  815.                 brelpos = mval - lval + outf->ef_bbase;
  816.             }
  817.             continue;
  818.                }
  819.            } else { 
  820.              if  (crel.r_symndx >= outf->ef_stcnt)
  821.                 lclash("Bad sy no");
  822.              csymb = outf->ef_stvec[symord[crel.r_symndx]];
  823.             if  (csymb == NULL)
  824.                 continue;
  825.             switch  (csymb->s_type)  {
  826.             case  S_UNDF:
  827.                 reassign(csymb, mval - lval);
  828.                 break;
  829.             case  S_ABS:
  830.                 if  (lval + csymb->s_value != mval)
  831.                     lclash("abs rel");
  832.                 break;
  833.             case  S_TEXT:
  834.                 if  (lval + csymb->s_value != mval)
  835.                     lclash("text rel");
  836.                 break;
  837.             case  S_DATA:
  838.                 if  (lval + csymb->s_value != mval)
  839.                     lclash("data rel");
  840.                 break;
  841.             case  S_BSS:
  842.                 if  (lval + csymb->s_value != mval)
  843.                     lclash("bss rel");
  844.                 break;
  845.              case  S_COMM:
  846.                 reassign(csymb, mval - lval);
  847.                 break;
  848.             }
  849.             mtstr.t_relsymb = csymb;
  850.             mtstr.t_reldisp = lval;
  851.         }
  852.     }
  853.  
  854.     if  (dhere || !donebrel)
  855.         return;
  856.  
  857.     zapdat(S_BSS, brelpos);
  858. }
  859.